package com.exam.utils.CertificateUtil;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

/**
 * @author 小聋包
 * @date 2024-04-29 16:18
 * @Version 1.0
 */
public class PDFUtil {

    private Document document;
    private PdfWriter writer;

    /**
     * 开启创建PDF对象
     *
     * @param pafPath ： 生成pdf的磁盘路径
     */
    public PDFUtil openDocument(String pafPath) throws FileNotFoundException, DocumentException {
        // 创建一个PDF文档对象
        Document document = new Document();
        // 将PDF文档对象与输出流关联，并指定生成PDF的磁盘路径
        writer = PdfWriter.getInstance(document, new FileOutputStream(pafPath));
        // 打开PDF文档
        document.open();
        // 将当前对象的document属性设置为新创建的PDF文档对象
        this.document = document;
        // 返回当前对象，以便进行链式调用
        return this;
    }

    /**
     * 添加图片背景
     *
     * @param imagePath ：图片路径
     * @param absoluteX ：左边距
     * @param absoluteY ：底边距
     */
    public PDFUtil addImage(String imagePath, float absoluteX, float absoluteY) throws IOException, DocumentException {
        // 创建图片实例
        Image tImgCover = Image.getInstance(imagePath);
        // 设置图片绝对位置
        tImgCover.setAbsolutePosition(absoluteX, absoluteY);
        // 获取图片高度
        float height = tImgCover.getHeight();
        // 获取图片宽度
        float width = tImgCover.getWidth();

        // 调用getPercent2方法计算缩放比例
        // int percent=getPercent(height, width);
        int percent = getPercent2(height, width);

        // 设置图片居中显示
        // tImgCover.setAlignment(Image.MIDDLE);

        // 根据缩放比例调整图片大小
        tImgCover.scalePercent(percent);// 表示是原来图像的比例;

        // 将图片添加到PDF文档中
        document.add(tImgCover);

        // 返回当前对象，以便进行链式调用
        return this;
    }

    /**
     * 添加Logo到PDF文档中
     *
     * @param imagePath Logo图片的文件路径
     * @param absoluteX Logo图片的左边距
     * @param absoluteY Logo图片的底边距
     * @return 返回当前PDFUtil对象，以便进行链式调用
     * @throws IOException 如果读取Logo图片文件时出现I/O错误
     * @throws DocumentException 如果向PDF文档中添加Logo图片时出现错误
     */
    public PDFUtil addLogo(String imagePath, float absoluteX, float absoluteY) throws IOException, DocumentException {
        // 从文件路径创建图片对象
        Image tImgCover = Image.getInstance(imagePath);
        // 设置图片的绝对位置
        tImgCover.setAbsolutePosition(absoluteX, absoluteY);
        // 将图片缩放为原来图像的20%
        tImgCover.scalePercent(20);// 表示是原来图像的比例;
        // 将图片添加到PDF文档中
        document.add(tImgCover);
        // 返回当前对象，以便进行链式调用
        return this;
    }

    /**
     * @param certificateContent :pdf证书的中文内容
     * @param x                  ：左边距
     * @param y                  ：底边距
     * @param contentStyle       ：中文内容的样式
     */
    public PDFUtil addContent(String certificateContent, float x, float y, ContentStyle contentStyle) throws DocumentException, IOException {

        if (contentStyle == null) {
            contentStyle = new ContentStyle();
        }

        // 获取PdfContentByte对象，用于绘制内容
        PdfContentByte canvas = writer.getDirectContent();

        // 在Windows系统下使用下面的代码创建字体
        // windows下用下面的
//        BaseFont bf = BaseFont.createFont(contentStyle.getTTFPath(),BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

        // 在Linux系统下使用下面的代码创建字体
        // linux用这个
        BaseFont bf = BaseFont.createFont("STSong-Light",
                "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);

        // 创建Font对象，设置字体样式
        Font secFont = new Font(bf, contentStyle.getFontSize(), contentStyle.getStyle(), contentStyle.getBaseColor());

        // 创建Phrase对象，将证书内容添加到Phrase中
        Phrase certificateContentPhrase = new Phrase(certificateContent, secFont);

        // 在PdfContentByte上绘制Phrase内容
        // 根据contentStyle的对齐方式，将certificateContentPhrase内容绘制到指定位置
        ColumnText.showTextAligned(canvas, contentStyle.getAlignment(), certificateContentPhrase, x, y, 0);

        // 返回当前PDFUtil对象，以便进行链式调用
        return this;
    }

    /**
     * 添加日期内容
     *
     * @param x 插入pdf左边距
     * @param y 插入pdf底边距
     */
    public PDFUtil addDateContent(float x, float y, ContentStyle contentStyle) throws DocumentException, IOException {

        // 如果传入的样式为null，则创建一个新的样式对象
        if (contentStyle == null) {
            contentStyle = new ContentStyle();
        }

        // 获取当前日期
        Date currentDate = DateTimeUtil.getCurrentDate();
        // 将日期转换为字符串
        String currentDateString = DateTimeUtil.DateToString(currentDate);

        // 获取PDF内容的画布
        PdfContentByte canvas = writer.getDirectContent();
        // 创建字体对象
        BaseFont bf = BaseFont.createFont(contentStyle.getTTFPath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 创建字体样式
        Font secFont = new Font(bf, contentStyle.getFontSize(), contentStyle.getStyle(), contentStyle.getBaseColor());
        // 创建日期内容的Phrase对象
        Phrase certificateDatephrase = new Phrase(currentDateString, secFont);
        // 在PDF画布上绘制日期内容，根据指定的对齐方式、内容、位置和旋转角度
        ColumnText.showTextAligned(canvas, contentStyle.getAlignment(), certificateDatephrase, x, y, 0);

        return this;
    }

    /**
     * 释放资源
     */
    public void close() {
        document.close();
    }

    /**
     * 第二种解决方案，统一按照宽度压缩
     * 这样来的效果是，所有图片的宽度是相等的，自我认为给客户的效果是最好的
     */
    public int getPercent2(float h, float w) {
        int p = 0;
        float p2 = 0.0f;

        // 计算压缩比例
        p2 = 595 / w * 100;

        // 打印压缩比例
        System.out.println("--" + p2);

        // 四舍五入取整
        p = Math.round(p2);

        // 返回压缩比例
        return p;
    }

    /**
     * 第一种解决方案
     * 在不改变图片形状的同时，判断，如果h>w，则按h压缩，否则在w>h或w=h的情况下，按宽度压缩
     */

    public int getPercent(float h, float w) {
        int p = 0;
        float p2 = 0.0f;

        // 如果高度大于宽度
        if (h > w) {
            // 按高度压缩，计算压缩比例
            p2 = 297 / h * 100;
        } else {
            // 否则，在宽度大于高度或宽度等于高度的情况下，按宽度压缩
            p2 = 210 / w * 100;
        }

        // 对压缩比例进行四舍五入
        p = Math.round(p2);

        // 返回压缩比例
        return p;
    }
}
